package com.neo.tiny.bpm.flowable.core.script.impl;

import com.neo.tiny.admin.api.dept.DeptApi;
import com.neo.tiny.admin.api.user.AdminUserApi;
import com.neo.tiny.admin.dto.dept.SysDeptDTO;
import com.neo.tiny.admin.dto.user.UserInfoDTO;
import com.neo.tiny.bpm.flowable.core.script.BpmTaskAssignScript;
import com.neo.tiny.bpm.service.task.BpmProcessInstanceExtService;
import com.neo.tiny.common.util.NumberUtils;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static java.util.Collections.emptySet;

/**
 * @Description: 分配给发起人的 Leader 审批的 Script 实现类
 * 目前 Leader 的定义是部门负责人
 * @Author: yqz
 * @CreateDate: 2022/10/16 11:46
 */
public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private DeptApi deptApi;
    @Resource
    @Lazy // 解决循环依赖
    private BpmProcessInstanceExtService bpmProcessInstanceService;

    protected Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, int level) {
        Assert.isTrue(level > 0, "level 必须大于 0");
        // 获得发起人
        ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
        Long startUserId = NumberUtils.parseUpperCaseLong(processInstance.getStartUserId());
        // 获得对应 leve 的部门
        SysDeptDTO dept = null;
        for (int i = 0; i < level; i++) {
            // 获得 level 对应的部门
            if (dept == null) {
                dept = getStartUserDept(startUserId);
                // 找不到发起人的部门，所以无法使用该规则
                if (dept == null) {
                    return emptySet();
                }
            } else {
                SysDeptDTO parentDept = deptApi.getDept(dept.getParentId());
                // 找不到父级部门，所以只好结束寻找。原因是：例如说，级别比较高的人，所在部门层级比较少
                if (parentDept == null) {
                    break;
                }
                dept = parentDept;
            }
        }

        return dept.getLeader() != null ? new HashSet<>(Collections.singletonList(dept.getId())) : emptySet();
    }

    private SysDeptDTO getStartUserDept(Long startUserId) {
        UserInfoDTO startUser = adminUserApi.getUser(startUserId);
        if (startUser.getDeptId() == null) { // 找不到部门，所以无法使用该规则
            return null;
        }
        return deptApi.getDept(startUser.getDeptId());
    }
}
